package com.example.qxfw.dysjrh.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.qxfw.common.SysResult;
import com.example.qxfw.dysjrh.dto.*;
import com.example.qxfw.dysjrh.entity.Msgmediumsmallscale;
import com.example.qxfw.dysjrh.entity.vo.*;
import com.example.qxfw.dysjrh.mapper.AdvNameMapper;
import com.example.qxfw.dysjrh.mapper.MsgmediumsmallscaleMapper;
import com.example.qxfw.dysjrh.service.IMsgmediumsmallscaleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author
 * @since 2024-12-11
 */
@Slf4j
@Service
public class MsgmediumsmallscaleServiceImpl extends ServiceImpl<MsgmediumsmallscaleMapper, Msgmediumsmallscale> implements IMsgmediumsmallscaleService {

    @Autowired
    private MsgmediumsmallscaleMapper msgmediumsmallscaleMapper;

    @Autowired
    private AdvNameMapper advNameMapper;

    @Override
    public SysResult getaaa(precipitationDto dto) {
/*        LocalDateTime startTime = LocalDateTime.now();
        Double precipitation = 0D;
        if (dto.getList() != null)
        for (Integer time : dto.getList()) {
            LocalDateTime endTime = LocalDateTime.now().minus(time, ChronoUnit.HOURS);
            Map<String, Double> map = msgmediumsmallscaleMapper.selectRangeTimeRain(startTime, endTime);
            if (map != null){
                precipitation += map.get("precipitation");
            }
        }
        if (dto.getList2() != null)
        for (Integer integer :  dto.getList2()) {
            LocalDateTime start = LocalDateTime.of(startTime.getYear(), startTime.getMonth(),
                    startTime.getDayOfMonth(), integer, 0);
            LocalDateTime end = LocalDateTime.of(startTime.getYear(), startTime.getMonth(),
                    startTime.getDayOfMonth(), integer - 1, 0);
            Map<String, Double> map = msgmediumsmallscaleMapper.selectRangeTimeRain(start, end);
            if (map != null){
                precipitation += map.get("precipitation");
            }
        }
        Map<String,Double> map = new HashMap<>(1);
        map.put("precipitation", precipitation);
        return SysResult.success(map);*/

        //代码优化：
        // 获取当前时间
        LocalDateTime startTime = LocalDateTime.now();
        // 初始化降水量为0
        Double precipitation = 0D;

        // 如果第一个列表不为空，则遍历这个列表来累加降水量
        if (dto.getList() != null) {
            for (Integer hoursAgo : dto.getList()) {
                // 根据小时数计算结束时间
                LocalDateTime endTime = startTime.minus(hoursAgo, ChronoUnit.HOURS);
                // 从数据库中获取指定时间范围内的降水量，并累加到总降水量中
                precipitation += getPrecipitationFromMap(msgmediumsmallscaleMapper.selectRangeTimeRain(startTime, endTime));
            }
        }

        // 如果第二个列表不为空，则遍历这个列表来累加降水量
        if (dto.getList2() != null) {
            for (Integer hourOfDay : dto.getList2()) {
                // 设置开始时间和结束时间，根据具体的小时来计算
                LocalDateTime start = LocalDateTime.of(startTime.getYear(), startTime.getMonth(), startTime.getDayOfMonth(), hourOfDay, 0);
                LocalDateTime end = hourOfDay == 0 ? start.minus(1, ChronoUnit.DAYS) : start.minus(1, ChronoUnit.HOURS);
                // 从数据库中获取指定时间范围内的降水量，并累加到总降水量中
                precipitation += getPrecipitationFromMap(msgmediumsmallscaleMapper.selectRangeTimeRain(start, end));
            }
        }

        // 创建一个HashMap来存储总降水量
        Map<String, Double> result = new HashMap<>(1);
        result.put("precipitation", precipitation);

        // 返回成功结果，包含降水量信息
        return SysResult.success(result);
    }

    @Override
    public SysResult getAutomaticDrybulbtempData(String funType) {
        // 获取今天的开始时间
        LocalDateTime startTime = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        // 获取今天结束时间
        LocalDateTime endTime = startTime.plusDays(1).minusNanos(1);
        // 拼接查询函数
        String fun = funType + "(drybulbtemp)";
        Double drybulbtemp = msgmediumsmallscaleMapper.getAutomaticDrybulbtempData(startTime, endTime, fun);
        if (drybulbtemp == null) drybulbtemp = 0D;
        // 创建一个HashMap来存储温度
        Map<String, Double> result = new HashMap<>(1);
        result.put("drybulbtemp", drybulbtemp);

        return SysResult.success(result);
    }

    /**
     * 雨量数据(累计雨量、小时雨强)
     * @param rainDto
     */
    @Override
    @DS("master")
    @Transactional
    public List<RainVo> getRainData(RainDto rainDto) {

        // 参数校验
        if (rainDto == null) {
            throw new IllegalArgumentException("RainDto cannot be null");
        }
        Integer rainType = rainDto.getRainType();
        LocalDateTime startTime = rainDto.getStartTime();
        LocalDateTime endTime = rainDto.getEndTime();
        String advcode = rainDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }

        try {
            // 日志记录
            log.info("Fetching rain data for type: {}, start time: {}, end time: {}", rainType, startTime, endTime);
            List<RainVo> rainDataVo = msgmediumsmallscaleMapper.getRainData(startTime, endTime, rainType, advName);
            for (RainVo rainVo : rainDataVo) {
                rainVo.setAdvcode(advcode);
            }
            return rainDataVo;
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch rain data", e);
            throw new RuntimeException("Failed to fetch rain data", e);
        }

    }




    /**
     * 查询时间段内最高温、最低温、平均温度
     * @param drybulbtempDto
     * @return
     */
    @DS("master")
    @Transactional
    @Override
    public List<DrybulbtempVo> getDrybulbtemp(DrybulbtempDto drybulbtempDto) {

        // 参数校验
        if (drybulbtempDto == null) {
            throw new IllegalArgumentException("DrybulbtempDto cannot be null");
        }
        String type = drybulbtempDto.getDrybulbtempType();
        LocalDateTime startTime = drybulbtempDto.getStartTime();
        LocalDateTime endTime = drybulbtempDto.getEndTime();
        String advcode = drybulbtempDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }
        try {
            // 日志记录
            log.info("Fetching dry bulb temperature data for type: {}, start time: {}, end time: {}", type, startTime, endTime);
            List<DrybulbtempVo> drybulbtempVo = msgmediumsmallscaleMapper.getDrybulbtemp(startTime, endTime, type, advName);
            for (DrybulbtempVo vo : drybulbtempVo) {
                vo.setAdvcode(advcode);
            }
            return drybulbtempVo;
//            return msgmediumsmallscaleMapper.getDrybulbtemp(startTime, endTime, type,advName);
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch dry bulb temperature data", e);
            throw new RuntimeException("Failed to fetch dry bulb temperature data", e);
        }


    }

    /**
     * 查询时间段内最小能见度
     * @param visibilityDto
     * @return
     */
    @DS("master")
    @Transactional
    @Override
    public List<VisibilityVo> getMinVisibility(VisibilityDto visibilityDto) {

        // 参数校验
        if (visibilityDto == null) {
            throw new IllegalArgumentException("VisibilityDto cannot be null");
        }

        LocalDateTime startTime = visibilityDto.getStartTime();
        LocalDateTime endTime = visibilityDto.getEndTime();
        String advcode = visibilityDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }
        try {
            // 日志记录
            log.info("Fetching minimum visibility data for start time: {}, end time: {}", startTime, endTime);
            List<VisibilityVo> minVisibilityVo = msgmediumsmallscaleMapper.getMinVisibility(startTime, endTime, advName);

            // 过滤掉 visibility 为 -65535 的对象
            List<VisibilityVo> filteredVisibilityVo = minVisibilityVo.stream()
                    .filter(vo -> vo.getVisibility() != -65535)
                    .collect(Collectors.toList());

            for (VisibilityVo visibilityVo : filteredVisibilityVo) {
                visibilityVo.setAdvcode(advcode);
            }
//            for (VisibilityVo visibilityVo : minVisibilityVo) {
//                visibilityVo.setAdvcode(advcode);
//            }

            return filteredVisibilityVo;
//            return minVisibilityVo;
//            return msgmediumsmallscaleMapper.getMinVisibility(startTime, endTime,advName);
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch minimum visibility data", e);
            throw new RuntimeException("Failed to fetch minimum visibility data", e);
        }

    }

    /**
     * 查询时间段内相对湿度
     * @param relhumidityDto
     * @return
     */
    @DS("master")
    @Transactional
    @Override
    public List<RelhumidityVo> getgetRelhumidity(RelhumidityDto relhumidityDto) {

        // 参数校验
        if (relhumidityDto == null) {
            throw new IllegalArgumentException("RelhumidityDto cannot be null");
        }

        LocalDateTime startTime = relhumidityDto.getStartTime();
        LocalDateTime endTime = relhumidityDto.getEndTime();

        String advcode = relhumidityDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }

        try {
            // 日志记录
            log.info("Fetching relative humidity data for start time: {}, end time: {}", startTime, endTime);

            List<RelhumidityVo> relhumidityVo = msgmediumsmallscaleMapper.getRelhumidity(startTime, endTime, advName);
            for (RelhumidityVo vo : relhumidityVo) {
                vo.setAdvcode(advcode);
            }
            return relhumidityVo;
//            return msgmediumsmallscaleMapper.getRelhumidity(startTime, endTime,advName);
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch relative humidity data", e);
            throw new RuntimeException("Failed to fetch relative humidity data", e);
        }


    }

    /**
     * 获取气压数据
     *
     * @param pressDto
     */
    @DS("master")
    @Transactional
    @Override
    public List<PressVo> getPressureData(PressDto pressDto) {

        // 参数校验
        if (pressDto == null) {
            throw new IllegalArgumentException("PressDto cannot be null");
        }
        LocalDateTime startTime = pressDto.getStartTime();
        LocalDateTime endTime = pressDto.getEndTime();
        String pressType = pressDto.getPressType();
        String advcode = pressDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }
        if (pressType == null || pressType.trim().isEmpty()) {
            throw new IllegalArgumentException("pressType cannot be null or empty");
        }

        try {
            // 日志记录
            log.info("Fetching pressure data for type: {}, start time: {}, end time: {}", pressType, startTime, endTime);
            List<PressVo> pressureVo = msgmediumsmallscaleMapper.getPressureData(startTime, endTime, pressType, advName);
            for (PressVo pressVo : pressureVo) {
                pressVo.setAdvcode(advcode);
            }
            return pressureVo;
//            return msgmediumsmallscaleMapper.getPressureData(startTime, endTime, pressType,advName);
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch pressure data", e);
            throw new RuntimeException("Failed to fetch pressure data", e);
        }

    }

    /**
     * 风速数据
     * @param windVelocityDto
     * @return
     */
    @DS("master")
    @Transactional
    @Override
    public List<WindVelocityVo> getWindVelocity(WindVelocityDto windVelocityDto) {

        // 参数校验
        if (windVelocityDto == null) {
            throw new IllegalArgumentException("WindVelocityDto cannot be null");
        }

        LocalDateTime startTime = windVelocityDto.getStartTime();
        LocalDateTime endTime = windVelocityDto.getEndTime();
        Integer windType = windVelocityDto.getWindType();
        String advcode = windVelocityDto.getAdvcode();

        String advName=advNameMapper.getcountByAdvcode(advcode);

        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("startTime and endTime cannot be null");
        }
        if (startTime.isAfter(endTime)) {
            throw new IllegalArgumentException("startTime must be before endTime");
        }
        if (windType == null) {
            throw new IllegalArgumentException("windType cannot be null");
        }

        try {
            // 日志记录
            log.info("Fetching wind velocity data for type: {}, start time: {}, end time: {}", windType, startTime, endTime);
            List<WindVelocityVo> windVelocityVoList = msgmediumsmallscaleMapper.getWindVelocity(startTime, endTime, windType,advName);

            for (WindVelocityVo windVelocityVo : windVelocityVoList) {
                windVelocityVo.setAdvcode(advcode);
                // 根据风速计算风力等级
            windVelocityVo.setWindSpeed(FengSuToFengJi(windVelocityVo.getWindVelocityData()));
                // 根据风级获取风速名称
            windVelocityVo.setFjName(GetWeatherFs(windVelocityVo.getWindVelocityData().toString()));
            }

            return windVelocityVoList;
        } catch (Exception e) {
            // 异常处理
            log.error("Failed to fetch wind velocity data", e);
            throw new RuntimeException("Failed to fetch wind velocity data", e);
        }

    }




    /**
     * 根据风速获取风级
     * @param fengsu
     * @return
     * @author dsq
     */
    public static int FengSuToFengJi(double fengsu) {
        if (fengsu > 0 && fengsu < 0.3) {
            return 0;
        } else if (fengsu > 0.2 && fengsu < 1.6) {
            return 1;
        } else if (fengsu > 1.5 && fengsu < 3.4) {
            return 2;
        } else if (fengsu > 3.3 && fengsu < 5.5) {
            return 3;
        } else if (fengsu > 5.4 && fengsu < 8) {
            return 4;
        } else if (fengsu > 7.9 && fengsu < 10.8) {
            return 5;
        } else if (fengsu > 10.7 && fengsu < 13.9) {
            return 6;
        } else if (fengsu > 13.8 && fengsu < 17.2) {
            return 7;
        } else if (fengsu > 17.1 && fengsu < 20.8) {
            return 8;
        } else if (fengsu > 20.7 && fengsu < 24.5) {
            return 9;
        } else if (fengsu > 24.4 && fengsu < 28.5) {
            return 10;
        } else if (fengsu > 28.4 && fengsu < 32.7) {
            return 11;
        } else if (fengsu > 36.9 && fengsu < 41.5) {
            return 12;
        }
        return 0;
    }

    /**
     * 获取风级名称
     * @param strFs
     * @return
     * @author dsq
     */
    public String GetWeatherFs(String strFs) {
        if (strFs.contains("级"))
            return strFs;
        if (strFs.trim() == "") {
            strFs = "0";
        } else {
            strFs = strFs.split("\\.")[0] == null ? strFs : strFs.split("\\.")[0];// 注意，在Java中split参数为string类型，并且特殊字符前面要加上\\作为转义符，如（'.','*','|','\'）'\'要用\\\\分隔
        }
        try {
            switch (strFs) {
                case "0":
                    strFs = "≤3级";
                    break;
                case "1":
                    strFs = "3-4级";
                    break;
                case "2":
                    strFs = "4-5级";
                    break;
                case "3":
                    strFs = "5-6级";
                    break;
                case "4":
                    strFs = "6-7级";
                    break;
                case "5":
                    strFs = "7-8级";
                    break;
                case "6":
                    strFs = "8-9级";
                    break;
                case "7":
                    strFs = "9-10级";
                    break;
                case "8":
                    strFs = "10-11级";
                    break;
                case "9":
                    strFs = "11-12级";
                    break;
                default:
                    break;
            }
            return strFs;
        } catch (Exception ex) {
            return "0";
        }
    }



    /**
     * 从给定的Map中获取降水量
     * 如果Map为空或者不包含"precipitation"键，则返回0
     *
     * @param map 包含降水量信息的Map
     * @return 降水量值，如果给定的Map为空或不包含降水量信息，则返回0
     */
    private double getPrecipitationFromMap(Map<String, Double> map) {
        if (map == null || !map.containsKey("precipitation")) {
            return 0D;
        }
        return map.get("precipitation");
    }


}

